package cn.dzz.util;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author ArkD42
 * @file OA
 * @create 2020 - 06 - 17 - 14:55
 */
public class TransactionManager {

    // 私有化
    private TransactionManager(){}

    // 当前线程对象，用以存放和绑定连接对象
    private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    // 我们需要一个数据源来获取连接，且事务正常执行的条件是来自于同一个连接对象才会有效
    private static DataSource dataSource ;

    /**
     * 我不希望只能从一个数据源获取，这个对象可以是多个的
     * @param dataSource
     */
    public static void setDataSource(DataSource dataSource) {
        TransactionManager.dataSource = dataSource;
    }

    /**
     * 首先是获取连接对象获取，如果当前线程实例中没有连接对象，则从这个数据源中获取
     * @return
     */
    public static Connection getCurrentThreadConnection(){
        Connection connection = null;
        try {
            connection = threadLocal.get();
            if (connection == null) {
                connection = dataSource.getConnection();
                threadLocal.set(connection);
            }
        } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
        return connection;
    }

    /**
     *  开启事务
     */
    public static void begin(){
        Connection connection = getCurrentThreadConnection();
        try {
            connection.setAutoCommit(false);
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
    }

    /**
     * 如果业务逻辑的每一步代码都正常执行，无任何异常，则开始提交
     */
    public static void commit(){
        Connection connection = getCurrentThreadConnection();
        try {
            connection.commit();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
    }

    /**
     * 如果业务逻辑发生了错误,立刻捕获，进入catch，执行回滚
     */
    public static void rollback(){
        Connection connection = getCurrentThreadConnection();
        try {
            connection.rollback();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
    }

    /**
     * 最后，不管是失败还是成功，都需要释放资源
     */
    public static void close(){
        Connection connection = getCurrentThreadConnection();
        try {
            connection.close();
            threadLocal.remove();
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
    }

}
